import { useEffect, useRef, useState } from 'react'
import styles from './style.module.scss'
import pianoSvg from '@/assets/svg/piano.svg'
import EventEmitter from '../EventEmitter'
import { showToast } from '../toast'

const defaultTimeout = 10000
type LoadingEvent = {
  showLoading: (
    text: string,
    timeout: number,
    closeFnRef: { v: CloseLoadingFn | null },
    timeOutText?: string
  ) => void
}
interface CloseLoadingFn {
  /**
   * waitTask需要等待的任务并且返回值
   */
  <T>(waitTask: Promise<T>): Promise<T>
  (): void
}
enum TypeLoadingState {
  loading,
  success,
  timeout,
}
const emit = new EventEmitter<LoadingEvent>()
let isUseToast = false
const Loading = () => {
  const [loading, setLoading] = useState(false)
  const [loadingText, setLoadingText] = useState('加载中')
  const loadingVersion = useRef(0)
  useEffect(() => {
    if (isUseToast) {
      console.warn('loading组件已存在，请勿重复使用')
    }
    emit.on('showLoading', (text, timeOut, closeFnRef, timeOutText) => {
      setLoading(true)
      setLoadingText(text)
      const currentVersion = ++loadingVersion.current
      let loadingState = TypeLoadingState.loading
      const timer = setTimeout(() => {
        if (currentVersion !== loadingVersion.current) return
        if (loadingState !== TypeLoadingState.loading) return
        loadingState = TypeLoadingState.timeout
        setLoading((loading) => {
          if (loading) {
            loadingVersion.current++
            showToast(timeOutText || `加载超时`)
          }
          return false
        })
      }, timeOut)
      // @ts-ignore
      closeFnRef.v = (task?: Promise<any>) => {
        const close = () => {
          if (currentVersion !== loadingVersion.current) return
          if (loadingState !== TypeLoadingState.loading) return
          loadingState = TypeLoadingState.success
          clearTimeout(timer)
          setLoading(false)
        }
        if (task) {
          return task.finally(close)
        }
        close()
      }
    })
    isUseToast = true
    return () => {
      isUseToast = false
    }
  }, [])
  if (!loading) {
    return <></>
  }
  return (
    <>
      <div className={styles['loading-component-mask']}></div>
      <div className={styles['loading-component-view']}>
        <div className={styles['logo-view']}>
          <img src={pianoSvg.src} className={styles['logo']} />
          <div className={styles['mask-cube']}></div>
        </div>
        <div className={styles['tips']}>{loadingText}</div>
      </div>
    </>
  )
}
export default function useLoading() {
  return { Loading, showLoading }
}
/**
 *
 * @param text loading文字
 * @param timeout 默认10秒
 * @param timeOutText 超时提示文字
 * @returns closeLoading
 */
export function showLoading(
  text = '加载中',
  timeout: number = defaultTimeout,
  timeOutText?: string
) {
  if (!isUseToast) {
    throw new Error('loading组件未使用，请使用useLoading')
  }
  const closeFnRef = { v: null as CloseLoadingFn | null }
  emit.emit('showLoading', text, timeout, closeFnRef, timeOutText)
  return closeFnRef.v!
}
